package custom

import (
	"bufio"
	"encoding/binary"
	"encoding/json"
	"gitee.com/tjccc/gomq/interface/protocol"
	protocol2 "gitee.com/tjccc/gomq/mq/protocol"
	"io"
)

type Payload struct {
	Data protocol.Msg
	Err  error
}

func ParseStream(reader io.Reader) <-chan *Payload {
	ch := make(chan *Payload)
	go parse0(reader, ch)
	return ch
}

func parse0(rawReader io.Reader, ch chan<- *Payload) {
	reader := bufio.NewReader(rawReader)
	for {
		totalLenBytes := make([]byte, 4)
		headerLenBytes := make([]byte, 4)
		_, err := reader.Read(totalLenBytes)
		if err != nil {
			ch <- &Payload{
				Err: err,
			}
		}
		_, err = reader.Read(headerLenBytes)
		if err != nil {
			ch <- &Payload{
				Err: err,
			}
		}
		totalLen := binary.BigEndian.Uint32(totalLenBytes)
		headerLen := binary.BigEndian.Uint32(headerLenBytes)
		headerBytes := make([]byte, headerLen)
		dataBytes := make([]byte, totalLen-headerLen)

		_, err = reader.Read(headerBytes)
		if err != nil {
			ch <- &Payload{
				Err: err,
			}
		}
		_, err = reader.Read(dataBytes)
		if err != nil {
			ch <- &Payload{
				Err: err,
			}
		}
		var msg protocol2.CustomMsg
		_ = json.Unmarshal(headerBytes, &msg)
		msg.Data = dataBytes
		ch <- &Payload{
			Data: &msg,
		}
	}
}

func ParseOne(rawReader io.Reader) *Payload {
	reader := bufio.NewReader(rawReader)
	totalLenBytes := make([]byte, 4)
	headerLenBytes := make([]byte, 4)
	_, err := reader.Read(totalLenBytes)
	if err != nil {
		return &Payload{
			Err: err,
		}
	}
	_, err = reader.Read(headerLenBytes)
	if err != nil {
		return &Payload{
			Err: err,
		}
	}
	totalLen := binary.BigEndian.Uint32(totalLenBytes)
	headerLen := binary.BigEndian.Uint32(headerLenBytes)
	headerBytes := make([]byte, headerLen)
	dataBytes := make([]byte, totalLen-headerLen)

	_, err = reader.Read(headerBytes)
	if err != nil {
		return &Payload{
			Err: err,
		}
	}
	_, err = reader.Read(dataBytes)
	if err != nil {
		return &Payload{
			Err: err,
		}
	}
	var msg protocol2.CustomMsg
	_ = json.Unmarshal(headerBytes, &msg)
	msg.Data = dataBytes
	return &Payload{
		Data: &msg,
	}
}
